某壳分析+修复
声明
仅限技术讨论,不得用于非法途径,后果自负。
分析中有什么错误欢迎大家指出
Java层分析
java层简单分析下流程,重点放在so文件分析
加固效果主要把类方法抽取(其实并没有抽取,还是在dex文件中,只是修改了accessFlags和codeoff)
通过查看AndroidManifest文件application被修改成壳入口的文件(此壳加固的原apk必须自己声明Application文件,否则会加固失败,加固网站也不会提示,只是在加固apk中有文本提示,感觉用户体验不是很好)
这里可以根据壳入口点自己跟着走一遍,我只说下大体流程吧
当执行完application就该执行AndroidManifest声明的activity,执行activity先执行里面的方法static方法,dofixc方法最终会执行到native的soInit和dofixs来修复方法
Native方法分析
通过java层分析,最终会加载libzuma.so
soinit方法分析,f5大法好
此壳f5一些函数损坏不是很严重,大部分都保留原样
方法大部分都是修复的,我只大体说下函数作用,其他具体自己看代码
主要3个方法
1. ali::AndroidDevice::AndroidDevice(androidDevice, env1);
主要判断sdk和dalvik还是art
AndroidDevice *__fastcall ali::AndroidDevice::AndroidDevice(int androidDevice, JNIEnv *env)
{
AndroidDevice *androidDevice1; // r4
JNIEnv *env1; // r7
int v4; // r6
int v5; // r0
int v6; // r0
_JNIEnv *v7; // r1
_BOOL4 v8; // r0
androidDevice1 = (AndroidDevice *)androidDevice;
env1 = env;
v4 = androidDevice + 4;
*(_DWORD *)(androidDevice + 20) = androidDevice + 4;
*(_DWORD *)(androidDevice + 24) = androidDevice + 4;
std::priv::_String_base<char,std::allocator<char>>::_M_allocate_block(androidDevice + 4, 16);
*(_BYTE *)androidDevice1->field_14 = 0;
androidDevice1->systemModeAddr = 0;
androidDevice1->field_30 = 0;
androidDevice1->field_34 = 0;
androidDevice1->dexAddr = 0;
androidDevice1->field_3C = 0;
androidDevice1->field_40 = 0;
androidDevice1->env = (int)env1;
std::string::operator=(v4, &unk_28EB8);
androidDevice1->systemModeBoolean = 0;
androidDevice1->system_sdk_version = ali::AndroidDevice::get_system_sdk_version((ali::AndroidDevice *)androidDevice1);// 魅族5.0.1->21
v5 = ali::AndroidDevice::get_runtime_by_mmap((ali::AndroidDevice *)androidDevice1);// 获取系统模式dalvik返回1 art返回2
v6 = ali::AndroidDevice::get_system_runtime((ali::AndroidDevice *)androidDevice1, v5);// 如果上边判断不出是dalvik还是art继续判断
androidDevice1->systemMode = v6;
androidDevice1->systemModeBoolean = (unsigned int)(v6 - 1) >= 1;// dalvik=false art=true
if ( j_strstr(androidDevice1->systemModeContent, "libaoc.so") )
androidDevice1->isYunOs = 1;
else
androidDevice1->isYunOs = ali::check_for_yun_os((JNIEnv *)androidDevice1->env, v7);// 有ro.yunos.version的话返回1
v8 = ali::check_for_yun_os_TV((ali *)androidDevice1->env, v7);
androidDevice1->isYunOsTv = v8; // yun_os_tv返回1
if ( v8 )
androidDevice1->isYunOs = 1;
return androidDevice1;
}
2.ali::AppInfo::AppInfo(appinfo, (_JNIEnv *)env1, (int)&v38);
主要是获取一些文件目录
AppInfo *__fastcall ali::AppInfo::AppInfo(ali::AppInfo *appinfo, _JNIEnv *env, int a3)
{
AppInfo *appinfo1; // r4
_JNIEnv *env1; // ST08_4
char *v5; // r7
const char **v6; // ST0C_4
const char *v7; // r2
appinfo1 = (AppInfo *)appinfo;
env1 = env;
v5 = (char *)appinfo + 0x18;
v6 = (const char **)a3;
std::string::string((int)appinfo);
std::string::string((int)v5);
std::string::string((int)&appinfo1->nativeLibraryDir);
std::string::string((int)&appinfo1->sourceDir);
std::string::operator=((std::string *)appinfo1, v6);
std::string::operator=(v5, &unk_28EB8);
std::string::operator=(&appinfo1->nativeLibraryDir, &unk_28EB8);
std::string::operator=(&appinfo1->sourceDir, &unk_28EB8);
appinfo1->field_60 = 0;
ali::AppInfo::initAppInfo((ali::AppInfo *)appinfo1, env1, v7);
return appinfo1;
}
3. ali::ZumaInfo::ZumaInfo(zumaInfo, (const char **)&v38);
读取zumadata信息到内存,然后把libzumadata信息读取出来,对应3个部分,头部,类信息,方法信息
ZumaInfo *__fastcall ali::ZumaInfo::ZumaInfo(ZumaInfo *zumaInfo, const char **a2)
{
ZumaInfo *zumaInfo1; // r4
const char **v3; // r3
const char *v4; // r1
const char *v5; // r2
zumaInfo1 = zumaInfo;
v3 = a2;
zumaInfo->zumaDataPathEnd = (int)zumaInfo;
zumaInfo->zumaDataPathStart = (int)zumaInfo;
zumaInfo->zero = 0;
if ( a2 != (const char **)zumaInfo )
{
v4 = a2[5];
v5 = v3[4];
if ( v5 != v4 )
std::string::_M_append((std::string *)zumaInfo, v4, v5);// /data/data/com.kangkai.test/files/ali-s/libzumadata.so加到zumainfo中
}
zumaInfo1->zumaDataMemory = ali::ZumaInfo::mmap_datafile_to_memory(zumaInfo1);// /data/data/com.kangkai.test/files/ali-s/libzumadata.so加入到内存
ali::ZumaInfo::gen_dex_info_list(zumaInfo1);
ali::ZumaInfo::gen_clazz_info_list(zumaInfo1);
ali::ZumaInfo::gen_method_info_list(zumaInfo1);
return zumaInfo1;
}
ali::ZumaInfo::gen_dex_info_list(zumaInfo1)
读取信息到开辟的dexcount*0x2c的内存中
int __fastcall ali::ZumaInfo::gen_dex_info_list(ZumaInfo *zumaInfo)
{
int dexCount; // r7
ZumaInfo *zumaInfo1; // r4
int v3; // r0
int i; // r1
int nextOffset1; // r0
ZumaHeader *zumaHeader; // r3
int v7; // r6
int nextOffset; // r5
int v9; // r6
int v10; // r2
int zumaDataMemory; // [sp+10h] [bp-20h]
int dexCount1; // [sp+14h] [bp-1Ch]
dexCount = zumaInfo->dexCount;
zumaInfo1 = zumaInfo;
v3 = j_malloc(0x2C * dexCount);
zumaInfo1->zumaDataHeader = v3;
if ( !v3 )
{
logoutRecord(
"gen_dex_info_list",
68,
6,
"RecordLog",
"dex_count (%d),dex_info_list_size (%d)",
dexCount,
0x2C * dexCount);
my_abort("jni/base/zuma-info.cpp", "gen_dex_info_list", 69, "malloc dex_info_list error");
}
j_memset(zumaInfo1->zumaDataHeader, 0, 0x2C * dexCount);
i = 0;
nextOffset1 = 0;
zumaDataMemory = zumaInfo1->zumaDataMemory;
dexCount1 = zumaInfo1->dexCount;
while ( i != dexCount1 ) // 把zumadata.so+4开始到0x18内容拷贝出来
{
zumaHeader = (ZumaHeader *)(zumaInfo1->zumaDataHeader + 0x2C * i);
v7 = *(_DWORD *)(zumaDataMemory + nextOffset1 + 0x14);
++i;
zumaHeader->field_0 = *(_DWORD *)(zumaDataMemory + nextOffset1 + 4);
zumaHeader->field_4 = *(_DWORD *)(zumaDataMemory + nextOffset1 + 8);
zumaHeader->field_8 = *(_DWORD *)(zumaDataMemory + nextOffset1 + 0xC);
nextOffset = *(_DWORD *)(zumaDataMemory + nextOffset1 + 0x10);
zumaHeader->classLength = v7;
v9 = *(_DWORD *)(zumaDataMemory + nextOffset1 + 0x18);
v10 = *(_DWORD *)(zumaDataMemory + nextOffset1 + 0x1C);
zumaHeader->field_14 = nextOffset;
zumaHeader->methodLength = v9;
zumaHeader->field_20 = nextOffset1 + v10;
zumaHeader->hex20 = 0x20;
zumaHeader->dexAddr = 0;
nextOffset1 += nextOffset;
}
return nextOffset1;
}
ali::ZumaInfo::gen_clazz_info_list(zumaInfo1)
把信息读取到开辟的内存中,然后会把内存中的数据排序
int __fastcall ali::ZumaInfo::gen_clazz_info_list(ZumaInfo *zumaInfo)
{
int v1; // r3
int dexCount; // r1
ZumaInfo *zumaInfo1; // r4
int i; // r5
int v5; // r2
int v6; // r0
int v7; // r3
int zumaData20; // r5
int v9; // r6
ZumaHeader *zumaHeader; // r3
unsigned __int8 *v11; // r1
int *v12; // r7
int v13; // r0
int zumaClass; // r3
unsigned __int8 *v15; // r1
int zumaClass1; // r7
unsigned __int8 *v17; // r1
unsigned __int8 *v18; // r1
int v19; // r0
int zumaClass2; // r3
unsigned int v22; // [sp+4h] [bp-2Ch]
int v23; // [sp+8h] [bp-28h]
int v24; // [sp+Ch] [bp-24h]
int v25; // [sp+10h] [bp-20h]
v1 = 0;
dexCount = zumaInfo->dexCount;
zumaInfo1 = zumaInfo;
for ( zumaInfo->zumaDataClassLength = 0;
;
zumaInfo->zumaDataClassLength = i + *(_DWORD *)(zumaInfo->zumaDataHeader + v5 + 0xC) )
{
i = zumaInfo->zumaDataClassLength; // 0x2cb
if ( v1 == dexCount )
break;
v5 = 0x2C * v1++;
}
v6 = j_malloc(0x14 * i); // 0x37DC
zumaInfo1->zumaClass = v6;
j_memset(v6, 0, 0x14 * i);
v7 = 0;
v22 = 0;
v25 = 0;
while ( 1 )
{
v24 = v7;
if ( v22 >= zumaInfo1->dexCount )
break;
zumaData20 = zumaInfo1->zumaDataMemory + v25 + *(_DWORD *)(zumaInfo1->zumaDataHeader + 0x2C * v22 + 0x18);// 读取zumadata从0x20位置开始
v9 = 0x14 * v7;
v23 = v7;
while ( 1 ) // 把zumadata从0x20信息拷贝到classinfo
// 0x10大小原样拷贝,从0x10开始拷贝zumadata20+0x10地址
{
zumaHeader = (ZumaHeader *)(zumaInfo1->zumaDataHeader + 0x2C * v22);
v11 = (unsigned __int8 *)zumaHeader->classLength;// 0x2cb类信息大小
if ( v23 - v24 >= (unsigned int)v11 )
break;
v12 = (int *)(zumaInfo1->zumaClass + v9);
v13 = ali::readUint32((ali *)zumaData20, v11);
zumaClass = zumaInfo1->zumaClass;
*v12 = v13;
*(_DWORD *)(zumaClass + v9 + 4) = ali::readUint32((ali *)(zumaData20 + 4), v15);
zumaClass1 = zumaInfo1->zumaClass + v9;
*(_DWORD *)(zumaClass1 + 8) = ali::readUint32((ali *)(zumaData20 + 8), v17);
v19 = ali::readUint32((ali *)(zumaData20 + 0xC), v18);
zumaClass2 = zumaInfo1->zumaClass + v9;
*(_DWORD *)(zumaClass2 + 0xC) = v19;
*(_DWORD *)(zumaClass2 + 0x10) = zumaData20 + 0x10;
zumaData20 += 4 * (v19 + 4);
++v23;
v9 += 0x14;
}
v25 += zumaHeader->field_14;
++v22;
v7 = v23;
}
return ali::quicksort_Clazz_Info_Struct(zumaInfo1->zumaClass, 0, zumaInfo1->zumaDataClassLength - 1);
}
ali::ZumaInfo::gen_method_info_list(zumaInfo1)
看具体注释吧
int __fastcall ali::ZumaInfo::gen_method_info_list(ZumaInfo *zumaInfo)
{
int v1; // r3
int v2; // r1
ZumaInfo *zumaInfo1; // r5
int v4; // r4
int v5; // r2
int v6; // r0
int result; // r0
ZumaHeader *zumaHeader; // r3
int v9; // r4
int zumaData90f0; // r4
int v11; // r6
ZumaHeader *zumaHeader1; // r3
unsigned __int8 *v13; // r1
int *v14; // r7
int v15; // r0
int methodInfo1; // r3
unsigned __int8 *v17; // r1
int methodInfo2; // r7
unsigned __int8 *v19; // r1
ali *v20; // r0
int methodInfo3; // r7
unsigned __int8 *v22; // r1
unsigned int v23; // [sp+4h] [bp-2Ch]
int v24; // [sp+8h] [bp-28h]
int v25; // [sp+Ch] [bp-24h]
int v26; // [sp+10h] [bp-20h]
int v27; // [sp+14h] [bp-1Ch]
v1 = 0;
v2 = zumaInfo->dexCount;
zumaInfo1 = zumaInfo;
for ( zumaInfo->zumaDataMethodLength = 0;
;
zumaInfo->zumaDataMethodLength = v4 + *(_DWORD *)(zumaInfo->zumaDataHeader + v5 + 0x10) )
{
v4 = zumaInfo->zumaDataMethodLength; // 0x1906
if ( v1 == v2 )
break;
v5 = 0x2C * v1++;
}
v6 = j_malloc(0x14 * v4); // 0x1f478
zumaInfo1->methodInfo = v6;
result = j_memset(v6, 0, 0x14 * v4);
v23 = 0;
v26 = 0;
v24 = 0;
while ( v23 < zumaInfo1->dexCount )
{
v25 = 0x2C * v23;
zumaHeader = (ZumaHeader *)(zumaInfo1->zumaDataHeader + 0x2C * v23);
v9 = 4 * zumaHeader->methodLength + 0x10 * zumaHeader->classLength;// 0x6418+0x2cb0=90c8
if ( v9 & 0xF ) // 0x8
v9 = v9 + 0x10 - (v9 & 0xF); // 0x90c8+0x10-0x8=0x90d0
zumaData90f0 = zumaInfo1->zumaDataMemory + v26 + zumaHeader->hex20 + v9;// 0x90d0+0x20=0x90f0
v27 = v24;
v11 = 20 * v24;
while ( 1 ) // method 0x0->*zudaData90f0 0x4->*zudaData90f0+0x4 0x8->*zudaData90f0+0x8
// 0xc->*zudaData90f0+0xc+*zumaHeader+0x20
// 0x10->*zumaHeader
{
zumaHeader1 = (ZumaHeader *)(zumaInfo1->zumaDataHeader + v25);
v13 = (unsigned __int8 *)zumaHeader1->methodLength;
if ( v24 - v27 >= (unsigned int)v13 )
break;
v14 = (int *)(zumaInfo1->methodInfo + v11);
v15 = ali::readUint32((ali *)zumaData90f0, v13);
methodInfo1 = zumaInfo1->methodInfo;
*v14 = v15;
*(_DWORD *)(methodInfo1 + v11 + 0x10) = *(_DWORD *)(zumaInfo1->zumaDataHeader + v25);
*(_DWORD *)(methodInfo1 + v11 + 4) = ali::readUint32((ali *)(zumaData90f0 + 4), v17);
methodInfo2 = zumaInfo1->methodInfo + v11;
*(_DWORD *)(methodInfo2 + 8) = ali::readUint32((ali *)(zumaData90f0 + 8), v19);
v20 = (ali *)(zumaData90f0 + 0xC);
zumaData90f0 += 0x10;
methodInfo3 = zumaInfo1->methodInfo + v11;
v11 += 0x14;
result = ali::readUint32(v20, v22) + *(_DWORD *)(zumaInfo1->zumaDataHeader + v25 + 0x20);
*(_DWORD *)(methodInfo3 + 0xC) = result;
++v24;
}
v26 += zumaHeader1->field_14;
++v23;
}
return result;
}
native doFixS分析
通过二分法查询了之前排序的类信息的偏移位置
JNIEnv *__fastcall Java_com_ali_mobisecenhance_Fix_doFixS(JNIEnv *env, int a2, int *cls, ali *classHash)
{
ali *classHash1; // r6
JNIEnv *env1; // r7
int v6; // r2
int classIndex; // r5
int v9; // r2
int v10; // [sp+8h] [bp-28h]
int *cls1; // [sp+Ch] [bp-24h]
unsigned int v12; // [sp+10h] [bp-20h]
classHash1 = classHash;
v10 = a2;
env1 = env;
cls1 = cls;
v12 = 0;
classIndex = ali::getClazzInfoRefByClzHash(classHash, (int)&v12, cls);// 在dump的classinfo中查找类信息
if ( classIndex == -1 )
return (JNIEnv *)logout(
(const char *)&unk_28914,
699,
5,
"RecordLog",
"can not find clazz_hash %X",
classHash1,
v10,
cls1);
if ( !ali::ZumaInfo::get_dex_file_adress(ali::g_zuma_infos, v12, v6, (int)&ali::g_zuma_infos) )
ali::get_all_dex_header_address_dalvik(*(ali **)(ali::g_app_infos + 96), v12, v9);
return fix_class(env1, v10, (int)cls1, classIndex);
}
fix_class方法
通过类偏移地址找到类信息,里面存储了需要修复的方法数量和方法偏移地址等
JNIEnv *__fastcall fix_class(JNIEnv *env, int a2, int cls, int classIndex)
{
_jmethodID *cls1; // ST24_4
JNIEnv *env1; // ST1C_4
unsigned __int8 *v6; // ST20_4
FixFunInfo *fixFunInfo; // r3
int classHash1; // ST2C_4
int v9; // ST30_4
int fixNativeCount1; // ST38_4
int methodOffset1; // ST3C_4
int v12; // r5
int dexAddr; // r0
int v15; // [sp+40h] [bp-18h]
cls1 = (_jmethodID *)cls;
env1 = env;
v6 = (unsigned __int8 *)a2;
fixFunInfo = (FixFunInfo *)(ali::g_zuma_infos->zumaClass + 0x14 * classIndex);
classHash1 = fixFunInfo->classHash;
v9 = fixFunInfo->field_4;
fixNativeCount1 = fixFunInfo->fixNativeCount; // 需要修复的native数量
methodOffset1 = fixFunInfo->methodOffset;
v12 = fixFunInfo->field_8; // 0
dexAddr = ali::ZumaInfo::get_dex_file_adress(ali::g_zuma_infos, fixFunInfo->field_8, (int)&v15, (int)fixFunInfo);
return ali::start_fix_this_class(env1, v6, cls1, dexAddr, classHash1, v9, v12, fixNativeCount1, methodOffset1);
}
start_fix_this_class方法
在dex中获取到类方法的地址,然后通过动态获取到类方法来修复
JNIEnv *__fastcall ali::start_fix_this_class(JNIEnv *result, unsigned __int8 *a2, _jmethodID *cls, int dexAddr, int a5, int a6, int a7, unsigned int nativeCount, int methodOffset)
{
int dexAddr1; // r4
unsigned int i; // r3
int methodIdIndex; // r7
unsigned __int16 *dexMethodId; // r3
unsigned __int16 protoIdIndex; // r6
char *methodName; // r7
char *methodSign; // r6
unsigned int v16; // [sp+14h] [bp-3Ch]
int string_ids_addr; // [sp+18h] [bp-38h]
int methodAddr; // [sp+1Ch] [bp-34h]
int className; // [sp+20h] [bp-30h]
int type_ids_addr; // [sp+24h] [bp-2Ch]
int method_ids_addr; // [sp+28h] [bp-28h]
char *env; // [sp+2Ch] [bp-24h]
_jmethodID *cls1; // [sp+30h] [bp-20h]
int proto_ids_addr; // [sp+34h] [bp-1Ch]
dexAddr1 = dexAddr;
env = (char *)result;
string_ids_addr = dexAddr + *(_DWORD *)(dexAddr + 0x3C);
cls1 = cls;
type_ids_addr = dexAddr + *(_DWORD *)(dexAddr + 0x44);
method_ids_addr = dexAddr1 + *(_DWORD *)(dexAddr1 + 0x5C);
proto_ids_addr = dexAddr + *(_DWORD *)(dexAddr + 0x4C);
for ( i = 0; ; i = v16 + 1 )
{
v16 = i;
if ( i >= nativeCount ) // 被native的方法数量
break;
methodAddr = 0x14 * ali::readUint32((ali *)(methodOffset + 4 * i), a2);// methodOffset=2e
// 0000A230=0x081c*0x14 1C 08 00 00 1D 08 00 00 B9 D7 9C DA 00 00 00 00
methodIdIndex = *(_DWORD *)(ali::g_zuma_infos->methodInfo + methodAddr + 4);// 0x4846
dexMethodId = (unsigned __int16 *)(method_ids_addr + 8 * methodIdIndex);// dex中某个地址
protoIdIndex = dexMethodId[1];
className = ali::get_class_name(dexAddr1, string_ids_addr, type_ids_addr, *dexMethodId);// typeIdIndex
methodName = (char *)ali::get_method_name(dexAddr1, string_ids_addr, method_ids_addr, methodIdIndex);
methodSign = ali::get_method_sig(dexAddr1, string_ids_addr, type_ids_addr, proto_ids_addr, protoIdIndex);
if ( ali::g_device_infos->systemModeBoolean )
ali::fix_method_in_art(
env,
cls1,
(_jmethodID *)className,
methodName,
methodSign,
*(_jmethodID **)(ali::g_zuma_infos->methodInfo + methodAddr + 8),
(_jmethodID *)dexAddr1);
else
ali::fix_method_in_dalvik(
env,
cls1,
(_jmethodID *)className,
methodName,
methodSign,
(_jmethodID *)(dexAddr1 + *(_DWORD *)(ali::g_zuma_infos->methodInfo + methodAddr + 8)),
(_jmethodID *)dexAddr1);
j_free(className);
j_free(methodName);
result = (JNIEnv *)j_free(methodSign);
}
return result;
}
int __fastcall ali::fix_dalvik_method_struct(ali *this, _JNIEnv *a2, int a3, unsigned int a4)
{
int v4; // r5
int v5; // r4
unsigned __int8 *v6; // r1
unsigned __int8 *v7; // r1
int codeOff; // r3
unsigned __int8 *v9; // r1
unsigned int v10; // r1
int result; // r0
unsigned __int8 *v12; // r1
unsigned int v13; // r1
v4 = a3;
v5 = (int)a2;
ali::getRegistersSize((ali *)a3, (unsigned __int8 *)a2);
ali::getOutsSize((ali *)v4, v6);
codeOff = v4 + 0x10;
if ( ali::g_device_infos->isYunOs )
{
*(_DWORD *)(v5 + 0x18) = codeOff;
*(_WORD *)(v5 + 0x20) = ali::getRegistersSize((ali *)v4, v7);
*(_WORD *)(v5 + 0x22) = ali::getOutsSize((ali *)v4, v9);
result = ali::getAccessFlags((ali *)*(unsigned __int16 *)(v5 + 6), v10);
*(_WORD *)(v5 + 6) = result;
}
else
{
*(_DWORD *)(v5 + 0x20) = codeOff;
*(_WORD *)(v5 + 0xA) = ali::getRegistersSize((ali *)v4, v7);
*(_WORD *)(v5 + 0xC) = ali::getOutsSize((ali *)v4, v12);
result = ali::getAccessFlags(*(ali **)(v5 + 4), v13);
*(_DWORD *)(v5 + 4) = result;
}
return result;
}
至此壳的流程基本走完了
分析完可知
header
修复
因为通过上面分析,我们能找到native方法对应的codeoff,所以可以动态写脚本来修复
但是会有一个问题,codeoff可能会超出原来大小,这样dex整个偏移都要变,修复太麻烦,不现实
参考文章 https://bbs.pediy.com/thread-220717.htm
通过修改baksmali源码来修复codeoff
说一下修复思路,源码我就不放出来了
1.通过上面源码分析,还原出gen_dex_info_list、gen_clazz_info_list、gen_method_info_list的代码
2.通过还原出的类,主动去加载所有需要修复的类
3.还原出修复类方法代码start_fix_this_class,由此可以得到codeoff
4.因为codeoff在dex文件中,所以直接在电脑64位系统加载到内存会有问题,我直接把类、方法、签名、codeoff保存到文件中
5.baksmali中去加载保存的文件信息,存到集合中
6.当baksmali反编译时候修复accessflag和codeoff
我分析的样本是之前的,修复脚本最新免费版一样适用
本文由看雪论坛 Roselia 原创
转载请注明来自看雪社区
往期热门阅读:
扫描二维码关注我们,更多干货等你来拿!